import { InjectRedis } from '@liaoliaots/nestjs-redis';
import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import Redis from 'ioredis';
import * as argon2 from 'argon2'
import { ResultUtils } from 'src/common/utils/result.utils';
import { RedisEnum } from 'src/enum/redis.enum';
import { Repository } from 'typeorm';
import { Admin } from './admin.entity';
import { LoginDto } from './dto/login.dto';
import { JwtService } from '@nestjs/jwt';
import { EditInfoDto } from './dto/edit-info.dto';
import { EditPasswordDto } from './dto/edit-password.dto';
import { CaptchaResultVo } from './vo/captcha.result.vo';
import { LoginResultVo } from './vo/login.result.vo';
import { GetInfoResultVo } from './vo/get-info.result.vo';
import { EditInfoResultVo } from './vo/edit-info.result.vo';
const uuid = require('uuid');
const captcha = require("svg-captcha");

@Injectable()
export class AdminService {
  constructor(
    @InjectRepository(Admin) private adminRepository:Repository<Admin>,
    @InjectRedis() private readonly redis: Redis,
    private jwt:JwtService
  ){}
  async captcha() {
    const cap = captcha.create({
      size: 4 ,//长度
      ignoreChars:"0o1il",//排除字符
      noise:3,//干扰线条数
      width: 120, // 宽度
      height: 36, // 高度
      color: true, // 验证码字符是否有颜色，默认是没有,如果设置了背景颜色，那么默认就是有字符颜色
      background: "#fff", // 背景色 可以自己改
    });
    const userKey = uuid.v4();
    const code = cap.text;
    await this.redis.set(`${RedisEnum.CAPTCHA}${userKey}`,code,'EX',RedisEnum.CAPTCHA_EXPIRE);
    const result:CaptchaResultVo = {
      captcherImg:cap.data,
      userKey
    };
    return ResultUtils.success(result);
  }

  async login(loginDto: LoginDto) {
    const {account,password,code,userKey} = loginDto;
    const serviceCode = await this.redis.get(`${RedisEnum.CAPTCHA}${userKey}`);
    if(serviceCode===null||serviceCode.toLowerCase()!==code.toLowerCase()) {
      this.redis.del(`${RedisEnum.CAPTCHA}${userKey}`);
      throw new BadRequestException('验证码错误');
    }
    const queryAdmin = await this.adminRepository.findOne({
      where:{account}
    });
    if(queryAdmin===null) {
      this.redis.del(`${RedisEnum.CAPTCHA}${userKey}`);
      throw new BadRequestException('用户名或密码错误');
    }
    const isPasswordValid = await argon2.verify(queryAdmin.password,password);
    if(!isPasswordValid) {
      this.redis.del(`${RedisEnum.CAPTCHA}${userKey}`);
      throw new BadRequestException('用户名或密码错误');
    }
    const token = await this.jwt.signAsync({id:queryAdmin.id});
    await this.redis.del(`${RedisEnum.CAPTCHA}${userKey}`);
    await this.redis.set(`${RedisEnum.TOKEN}${token}`,token,'EX',RedisEnum.TOKEN_EXPIRE);
    const result:LoginResultVo = {
      account:queryAdmin.account,
      headimg:queryAdmin.headimg,
      id:queryAdmin.id,
      nickname:queryAdmin.nickname,
      token
    };
    return ResultUtils.success(result);
  }

  async logout(req) {
    const token = req.headers.authorization.split('Bearer ')[1];
    await this.redis.del(`${RedisEnum.TOKEN}${token}`);
    return ResultUtils.success();
  }

  async getInfo(req) {
    const id = req.user?.id;
    const admin = await this.adminRepository.findOne({where:{id}});
    const result:GetInfoResultVo = {
      id:admin.id,
      account:admin.account,
      headimg:admin.headimg,
      nickname:admin.nickname
    };
    return ResultUtils.success(result);
  }

  async editInfo(req,editInfoDto:EditInfoDto) {
    const id = req.user?.id;
    const queryAdmin = await this.adminRepository.findOne({where:{account:editInfoDto.account}});
    if(queryAdmin&&queryAdmin.id!==id) {
      throw new BadRequestException('账号已存在')
    }
    const admin = await this.adminRepository.findOne({ where: {id} });
    const newAdmin = this.adminRepository.merge(admin,editInfoDto);
    const updateAdmin = await this.adminRepository.save(newAdmin);
    const result:EditInfoResultVo = {
      id:updateAdmin.id,
      account:updateAdmin.account,
      headimg:updateAdmin.headimg,
      nickname:updateAdmin.nickname,
      create_time:updateAdmin.create_time,
      update_time:updateAdmin.update_time
    };
    return ResultUtils.success(result)
  }

  async editPassword(req,editPasswordDto:EditPasswordDto) {
    if(editPasswordDto.password!==editPasswordDto.password2){
      throw new BadRequestException('确认密码不一致')
    }
    editPasswordDto.password = await argon2.hash(editPasswordDto.password);
    const id = req.user?.id
    const admin = await this.adminRepository.findOne({ where: {id} });
    const newAdmin = this.adminRepository.merge(admin,editPasswordDto);
    await this.adminRepository.save(newAdmin)
    return ResultUtils.success()
  }
}
